package com.mww.chatroom.controller;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.mww.chatroom.component.OnlineUserManager;
import com.mww.chatroom.mapper.MessageMapper;
import com.mww.chatroom.mapper.MessageSessionMapper;
import com.mww.chatroom.model.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import java.io.IOException;
import java.util.List;

@Component
public class WebSocketAPI extends TextWebSocketHandler {
    @Autowired
    private MessageMapper messageMapper;
    @Autowired
    private MessageSessionMapper messageSessionMapper;
    @Autowired
    private OnlineUserManager onlineUserManager;
    private ObjectMapper objectMapper = new ObjectMapper();//spring中内置的
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        System.out.println("[WebsocketAPI]连接成功");
     User user = (User) session.getAttributes().get("user");
     if(user==null){
         return;
     }
        System.out.println("当前获取到的userId="+user.getUserId());
     //把这个键值对存起来
        onlineUserManager.online(user.getUserId(),session);
    }

    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        System.out.println("[WebsocketAPI]收到消息"+message.toString());
        //1.获取用户信息，后续要进行消息的转发啥的
        User user = (User) session.getAttributes().get("user");
        if(user==null){
            System.out.println("[WebSocketAPI] user == null ! 未登录用户，无法进行消息的转发");
            return;
        }
        //2.针对请求进行解析  把json字符串转化为java对象
        //String messageString = message.getPayload();
      MessageRequest req = objectMapper.readValue(message.getPayload(), MessageRequest.class);
        if(req.getType().equals("message")){
            //就对消息进行转发
            transferMessage(user,req);
        }else {
            System.out.println("[WebSocketAPI] req.type有误"+message.getPayload());
        }
    }

    //通过这个方法完成实际的转发工作
    private void transferMessage(User fromuser, MessageRequest req) throws IOException {
        //1.先构造一个带转发的响应对象
        MessageResponse resp = new MessageResponse();
        resp.setType("message");
        resp.setFromId(fromuser.getUserId());
        resp.setFromName(fromuser.getUsername());
        resp.setSessionId(req.getSessionId());
        resp.setContent(req.getContent());
        //把java对象转换成json格式字符串
        String respJson =objectMapper.writeValueAsString(resp);
        System.out.println("[transferMessage] respJson"+respJson);
        //2.更具请求的sessionId获取到这个MessageSession里都有那些用户，通过查询数据库
     List<Friend> friends = messageSessionMapper.getFriendsBySessionId(req.getSessionId(),fromuser.getUserId());
//由于最终法消息需要给发送消息的人也发一份
        //把当前用户也添加到上述List里面
        Friend myself = new Friend();
        myself.setFriendId(fromuser.getUserId());
        myself.setFriendName(fromuser.getUsername());
        friends.add(myself);
        //3.循环遍历上述列表，给列表的每个用户发一份响应
        for(Friend friend : friends){
            //知道了每个用户的userId,京一部的查询刚才准备好的OnlineUserManager,就知道了对应的WebSocketSession
            //从而进行了发送消息
            WebSocketSession webSocketSession = onlineUserManager.getSession(friend.getFriendId());
            if(webSocketSession==null){
                //如何该用户不在线，先不发送
                continue;
            }
            webSocketSession.sendMessage(new TextMessage(respJson));
        }

        //除了给查询到的好友发送，也要给自己发送一份，方便实现自己在客户端上显示自己发送的消息
        //注意:一个会话中可能有多个用户（群聊）,虽然客户端没有支持群聊（前端写起来比较麻烦）,后端无论是API还是数据库都是支持群聊
        //此处的转发逻辑也一样让他可以支持群聊
        //4.转发的消息还需要放到数据库里，后续用户下线之后，重新上线，还可以通过历史消息的方式获取到之前的消息
        //需要在message表中写入一条记录
        Message message = new Message();
        message.setFromId(fromuser.getUserId());
        message.setSessionId(req.getSessionId());
        message.setContent(req.getContent());
        //像自增主键和时间，都可以让SQL在数据库自动生成
        messageMapper.add(message);


    }
    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        System.out.println("[WebsocketAPI]连接异常"+exception.toString());

        User user = (User) session.getAttributes().get("user");
        if(user!=null){
            return;
        }
        onlineUserManager.offline(user.getUserId(),session);
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        System.out.println("[WebsocketAPI]连接关闭"+status.toString());
        User user = (User) session.getAttributes().get("user");
        if(user==null){
            return;
        }
        onlineUserManager.offline(user.getUserId(),session);
    }
}
